using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;


namespace BiztalkScriptingFunctoidExplorer
{
    class Library
    {
        private List<FileInfo> fiALL = new List<FileInfo>();
        private FunctoidInfo funci = new FunctoidInfo();

        // Returns an array of fileinfo objects for any found biztak map files (.btm)
        public FileInfo[] GetMaps(string path)
        {
            if (path == null | path == string.Empty)
                throw new System.ArgumentException("Search path must be specified");

            fiALL.Clear();
            GetMapFiles(path);
            return fiALL.ToArray();

        }


        // Populates FunctoidInfo dataset with info from btm file
        public void UpdateFunctoidData(FileInfo fi, Boolean FilterDuplicates)
        {
            XmlDocument BizMapXML = new XmlDocument();
            BizMapXML.Load(fi.FullName);

            XmlNodeList FunctoidsXML = BizMapXML.DocumentElement.SelectNodes("/mapsource/Pages/Page/Functoids/Functoid/ScripterCode/Script");

            foreach (XmlNode tmpXMLNode in FunctoidsXML)
            {

                XmlNode parentXML = tmpXMLNode.SelectSingleNode("../..");

                string name = parentXML.Attributes["Label"].Value;

                string mapfile = fi.FullName;
                string scriptlang = tmpXMLNode.Attributes["Language"].Value;
                string assembly;
                string assemblypath;
                string classused;
                string method;
                string code;

                assembly = "";
                assemblypath = "";
                classused = "";
                method = "";
                code = "";

                switch (scriptlang)
                {
                    case "ExternalAssembly":
                        {
                            assembly = tmpXMLNode.Attributes["Assembly"].Value;
                            assemblypath = tmpXMLNode.Attributes["AssemblyPath"].Value;
                            classused = tmpXMLNode.Attributes["Class"].Value;
                            method = tmpXMLNode.Attributes["Function"].Value;
                            break;
                        }
                    case "CSharp":
                    case "Xslt":
                    case "XsltCallTemplate":
                    case "VbNet":
                        {
                            XmlNode cscodeXML = tmpXMLNode.FirstChild;
                            code = cscodeXML.Value;
                            break;
                        }
                    default:
                        // Ignore any other script language entries, are there any more required?
                        continue;
                }

                if (FilterDuplicates)
                {
                    if (scriptlang == "ExternalAssembly")
                    {
                        String expr = string.Format("ScriptLanguage = 'ExternalAssembly' AND MapFileName = '{0}' AND class = '{1}' AND Method = '{2}'", mapfile, classused, method);
                        System.Data.DataRow[] resltset = funci.Functoids.Select(expr);
                        if (resltset.GetLength(0) > 0)
                            continue;
                    }
                    else
                    {
                        try
                        {
                            string expr = string.Format("ScriptLanguage <> 'ExternalAssembly' AND MapFileName = '{0}' AND Code = '{1}'", mapfile, code);
                            System.Data.DataRow[] resltset = funci.Functoids.Select(expr);
                            if (resltset.GetLength(0) > 0)
                                continue;
                        }
                        // Catch exceptions thrown by select statement this can happen if code string contains control characters
                        // If this happens let the entry through into the grid.
                        catch (System.Exception ex)
                        {
                            // do nothing swallow exception
                        }
                    }
                }
                
                funci.Functoids.AddFunctoidsRow(name, scriptlang, assembly, assemblypath, classused, method, code, mapfile);
            }


        }


        // Recurses through directories from specified start point searching for biztalk map files (.btm) 
        private void GetMapFiles(string path)
        {
            DirectoryInfo di = new DirectoryInfo(path);
            FileInfo[] files = di.GetFiles();

            foreach (FileInfo fi in files)
            {
                if (fi.Extension == ".btm")
                    fiALL.Add(fi);
            }

            foreach (DirectoryInfo diRec in di.GetDirectories())
            {
                GetMapFiles(diRec.FullName);
            }

        }

        // Propert exposing the populated funtoid information dataset
        public FunctoidInfo FunctoidInfoDS
        {
            get { return funci; }
            //set { funci = value; }
        }
	

    }
}
